
---@class CityPlayerInfo
CityPlayerInfo = Class("CityPlayerInfo")
function CityPlayerInfo:ctor()
    self.roleId = 0;
    self.roleName = "";
    self.head = 0
    self.genes = {}
    self.emojiId = nil
    self.weaponLevel = 0
end

---@class CityPlayer
CityPlayer = Class("CityPlayer")

function CityPlayer:ctor()
    ---@type CityPlayerInfo
    self.info = nil
    self.ModelSpine = nil;
    self.CharObj = nil;
    self.ModelPet = nil
    self.animObj = nil
    self.IsChangePet = false
    self.isChangeEmoji = false
    self.IsLoad = 0;
    self.isDestroy = false
    self.petGoWrapper = nil
end
function CityPlayer:Destroy()
    destroy(self.CharObj)
    if self.ModelSpine then
        self.ModelSpine:Dispose()
        self.IsLoad = 0
    end
    self.ModelSpine = nil
    self.CharObj = nil
    self.CharObjAniTrans = nil
    self.animObj = nil
    destroy(self.ModelPet)
    self.ModelPet = nil
    self.isLeft = false
    self.isDestroy = true
    self:DestroyPet()
    utimer.remove(self.emojiTimerId)
    self.emojiTimerId = nil
end
function CityPlayer:CanLoad()
    if (self.IsLoad ~= 0 or self.info.head == nil) then
        return false
    end
    return true
end

function CityPlayer:IsLoadDone()
    return self.IsLoad == CityPlayerMgr.LoadState.LoadComplete
end
function CityPlayer:UpdateInfoMsg(msg)
    if not self.info then
        self.info = CityPlayerInfo.New()
    end
    self.isDestroy = false
    self.info.roleId = tostring(msg.roleId)
    self.info.roleName = msg.roleName
    self.info.head = msg.head
    self.info.headPic = msg.headPic
    self.info.titleId = msg.titleId
    self:ChangePetInfo(msg.genes)
    self.isChangeEmoji = self.info.emojiId ~= msg.emojiId
    self.info.emojiId = msg.emojiId;
    self.info.weaponLevel = msg.weaponLevel
    self.info.unionName = msg.unionName;
    self.info.weaponQuality = msg.rank
end
function CityPlayer:ChangePetInfo(genes)
    self.IsChangePet = self:CheckPetChange(genes)
    if genes == nil or #genes ~= PetManager.PetPart.Ornament then
        table.clear(self.info.genes)
    else
        self.info.genes = genes
    end
end
function CityPlayer:CheckPetChange(_genes)
    if _genes == nil then
        return true
    end
    if #self.info.genes  == 0 and _genes and #_genes > 0 then
        return true
    end
    for k,v in pairs(self.info.genes) do
        if v ~= _genes[k] then
            return true
        end
    end
    return false
end
function CityPlayer:Load(parent)
    if self:IsLoadDone() then
        local changeEmoji = self.isChangeEmoji
        local changePet = self.IsChangePet
        if self.isChangeEmoji then
            self:ShowEmoji()
        end
        if self.IsChangePet then
            self:ShowPet()
        end

        return changeEmoji and changePet
    end
    if not self:CanLoad() then
        return false
    end
    self.isDestroy = false
    self.IsLoad = CityPlayerMgr.LoadState.LoadingPlayer
    --local modelId = logicMgr.SkinManager.getHeroModelIdBySkinId(self.info.head)
    local cfg = G.dataTable["t_hero"][tostring(self.info.head)];
    --local cfg = G.dataTable["t_hero"][tostring(modelId)];
    if cfg and self.info.headPic then
        self.modlename = cfg.f_HeroModel;
        local path = logicMgr.SkinManager.GetHeroModelPathBySkinId(self.info.headPic)
        resMgr:LoadModelPrefab(path, function(go)
            if self.isDestroy then
                return
            end
            self:CreatePlayer(go,parent)
        end)
    else
        logError("CityPlayer 找不到modelId "..tostring(self.info.head))
    end

    return true
end
function CityPlayer:CreatePlayer(go,parent)
    self.ModelSpine = newGComponent("HeroPos", "UICity")
    self.ModelSpine.onClick:Add(self.ClickOtherPlayer,self)
    local titleId = self.info.titleId;
    local titleItem =  self.ModelSpine:GetChild("Badge");
    local ctrlName = self.ModelSpine:GetController("onlyName")
    if titleId and titleId > 0 then
        ctrlName.selectedIndex = 0
        titleItem.visible = true;
        titleItem:GetController("show").selectedIndex = 1;
        titleItem:GetChild("icon").url = "ui://ICONAtlas/".. G.dataTable["t_medal"][tostring(titleId)].f_MedalPic;
    else
        ctrlName.selectedIndex = 1
        titleItem.visible = false;
        titleItem:GetController("show").selectedIndex = 0;
    end
    self.ModelSpine.onTouchBegin:Add(self.OnTouchBegin,self)
    self.ModelSpine.onTouchMove:Add(self.OnTouchMove,self)
    self.ModelSpine.onTouchEnd:Add(self.OnTouchEnd,self)
    parent:AddChild(self.ModelSpine)

    self.orX , self.orY = self:GetRandomBornXY()
    self.ModelSpine:SetXY(self.orX, self.orY)
    self.ModelSpine.name = self.info.roleId;
    self.CharObj = newObject(go);
    self.CharObj:SetActive(true)
    self.CharObj.name = "obj";
    self.CharObjShadow = self.CharObj.transform:Find("shadow").gameObject
    self.CharObj:AddComponent(TCanvas)
    self.CharObj:AddComponent(TChangeSortingOrder)
    ---@type GGraph
    local graph = self.ModelSpine:GetChild("model")
    graph:SetNativeObject(GoWrapper.New(self.CharObj))
    local layer = graph.displayObject.gameObject.layer
    if layer ~= LayerMask.NameToLayer("UI") then
        utimer.timeCall(function()
            if not HelperFunc.IsNull(self.CharObj) and not HelperFunc.IsNull(graph) then
                Util.SetLayerMask(self.CharObj,graph.displayObject.gameObject.layer,true)
            end
        end,66)
    end
    Util.SetLayerMask(self.CharObj,layer,true)
    Util.Lua_SetLocalPositionXYZ(self.CharObj.transform,0,0,0);
    Util.Lua_SetLocalScaleXYZ(self.CharObj.transform,88, 88, 88);
    ---@type Spine.Unity.SkeletonAnimation
    self.CharObjAniTrans = self.CharObj.transform:Find("Animation")
    self.animObj = self.CharObjAniTrans.gameObject
    Util.Lua_SetLocalRotationXYZ(self.CharObjAniTrans,0,0,0)
    --self.CharObjAniTrans.localEulerAngles=Vector3(0,0,0);
    --HelperFunc.RandomDir(self.CharObjAniTrans)
    local ran = math.random()
    self:ChangeDir(ran > 0.5)
    self.animObj.layer = 5;

    local textMeshPro = self.ModelSpine:GetChild("Name");
    textMeshPro.text = string.TextColor(self.info.roleName,"#C6C6C6" ) ;
    local textMeshPro1 = self.ModelSpine:GetChild("Name1");
    textMeshPro1.text = string.TextColor(self.info.roleName,"#C6C6C6" ) ;
    logicMgr.ChatManager.GMColor(textMeshPro,self.info.roleName,Color.HexToColor("#C6C6C6"))
    logicMgr.ChatManager.GMColor(textMeshPro1,self.info.roleName,Color.HexToColor("#C6C6C6"))

    local ctlYouandme = self.ModelSpine:GetController("youandme");
    ctlYouandme.selectedIndex = 1;
    --显示公会名称
    local textGuildName = self.ModelSpine:GetChild("Regiment");
    local unionName = self.info.unionName;
    local ctrlUnionName = self.ModelSpine:GetController("Regiment")
    if unionName then
        print("角色名:"..self.info.roleId.."    公会名：".. unionName);
    end
    if unionName and unionName ~= '' then
        ctrlUnionName.selectedIndex = 1;
        textGuildName.text = string.TextColor(string.format(getLanguage("GuildInvestment_1137"),unionName),"#C6C6C6" );
    else
        ctrlUnionName.selectedIndex = 0;
    end

    --skin
    local skinCfg = G.dataTable["t_roleconfig"][self.modlename]
    local offsetBar = Entity:GetTableValue(skinCfg, "BloodBar_Position");
    if offsetBar == nil or offsetBar == "" then
        offsetBar = 0;
    end
    offsetBar = -offsetBar + 170
    titleItem.y = offsetBar
    textMeshPro.y = offsetBar
    textMeshPro1.y = offsetBar + 20
    textGuildName.y = offsetBar + 32

    --if skinCfg and not string.IsNilOrEmpty(skinCfg.skin) then
    --    Util.SetSkin(self.animObj, skinCfg.skin);
    --ends
    logicMgr.EquipManager.setWeaponSkin(self.animObj, self.info.head, false, self.info.weaponQuality);

    Util.PlayAction(self.animObj, CityPlayerMgr.getAnimationName(self.modlename, "idleFree"));
    self.IsLoad = CityPlayerMgr.LoadState.LoadComplete
    self:ShowPet()
    self:ShowEmoji()
    CityPlayerMgr.SortPlayerOrder()
end
function CityPlayer:ChangeDir(isLeft)
    if HelperFunc.IsNull(self.CharObjAniTrans) then
        return
    end
    self.isLeft = isLeft
    local oriAngles = self.CharObjAniTrans.localEulerAngles
    if isLeft then
        oriAngles.y = 180
    else
        oriAngles.y = 0
    end
    self.CharObjAniTrans.localEulerAngles = oriAngles
    self:ChangePetDir()
end
function CityPlayer:ChangePetDir()
    if HelperFunc.IsNull(self.ModelPet) then
        return
    end
    local pos = PetManager.PetLeftPosition
    local rot = PetManager.PetLeftRotation
    if self.isLeft then
        pos = PetManager.PetRightPosition
        rot = PetManager.PetRightRotation
    end
    Util.Lua_SetLocalPositionXYZ(self.ModelPet,pos.x,pos.y,pos.z)
    Util.Lua_SetLocalRotationXYZ(self.ModelPet.transform,rot.x,rot.y,rot.z);
end
function CityPlayer:GetRandomBornXY()
    local forward = 1
    local r = math.random(1,2)
    if r == 1 then
        forward = forward * -1
    end
    local randomCityArea
    local randomNum = math.random(1,100)
    for index, value in ipairs(CityPlayerMgr.HeroLocaltionPosRatio) do
        if randomNum >= value[1] and randomNum <= value[2] then
            randomCityArea = index
        end
    end
    local x = CityPlayerMgr.HeroLocaltionPos[randomCityArea] + forward * math.random(20, 300)
    x = math.min(x,CityPlayerMgr.POS_X_MAX)
    x = math.max(x,CityPlayerMgr.POS_X_MIN)
    local y = math.random(CityPlayerMgr.POS_Y_MIN,CityPlayerMgr.POS_Y_MAX)
    return x,y
end
function CityPlayer:ShowPet()
    if self.ModelSpine == nil then
        self:DestroyPet()
        return
    end
    --logError("CityPlayer:ShowPet "..#self.info.genes)
    local _petModelInfo = {}
    _petModelInfo.modelGO = self.ModelPet
    _petModelInfo.parentGO = self.ModelSpine:GetChild("model")
    _petModelInfo.petId = 0

    local _otherPetGenes = self.info.genes
    local _otherModelName = self.modlename
    local _otherAnimNames = {}
    _otherAnimNames[1] = CityPlayerMgr.getAnimationName(_otherModelName, "idleFree")
    _otherAnimNames[2] = CityPlayerMgr.getAnimationName(_otherModelName, "run")

    if _otherPetGenes and #_otherPetGenes == PetManager.PetPart.Ornament then
        if  _petModelInfo.modelGO and self.IsChangePet then--pet只是换皮肤走着里
            _petModelInfo.modelWrapper = self.petGoWrapper
            PetManager.PetModelRefresh(_petModelInfo,_otherPetGenes,true)
            CityPlayerMgr.AddAI(self.ModelSpine,_otherAnimNames,_petModelInfo.modelGO)
            self.IsChangePet = false
            self.IsLoad = CityPlayerMgr.LoadState.LoadComplete
        else
            self.IsLoad = CityPlayerMgr.LoadState.LoadingPet
            self.IsChangePet = false

            _petModelInfo.modelGO = nil
            resMgr:LoadModelPrefab(PetManager.PetModelPrefab,function(go)
                if self.isDestroy then
                    return
                end
                if _petModelInfo.modelGO then
                    destroyImmediate(_petModelInfo.modelGO)
                    _petModelInfo.modelGO = nil
                end
                _petModelInfo.modelGO = newObject(go)
                self.ModelPet = _petModelInfo.modelGO
                if self.petGoWrapper == nil then
                    self.petGoWrapper = GoWrapper.New()
                end
                _petModelInfo.modelWrapper = self.petGoWrapper

                PetManager.PetModelFirstSet(_petModelInfo,_otherPetGenes,true,PetManager.PetLeftPosition,Vector3.New(0.4,0.4,1))
                CityPlayerMgr.AddAI(self.ModelSpine,_otherAnimNames,_petModelInfo.modelGO)
                self:ChangePetDir()
                --this.uICityRunAI:AddObj(_otherModelSpine,_otherAnimNames,_petModelInfo.modelGO)
                self.IsLoad = CityPlayerMgr.LoadState.LoadComplete
            end)
        end
    else
        self.IsChangePet = false
        CityPlayerMgr.AddAI(self.ModelSpine,_otherAnimNames)
    end
end

function CityPlayer:DestroyPet()
    if self.ModelPet then
        destroy(self.ModelPet)
    end
    self.ModelPet = nil
    if self.petGoWrapper then
        --destroyImmediate(self.petGoWrapper.wrapTarget)
        self.petGoWrapper:Dispose()
    end
    self.petGoWrapper = nil
end
--显示表情
function CityPlayer:ShowEmoji()
    local modelSpine = self.ModelSpine
    local emojiId = self.info.emojiId
    self.info.emojiId = nil
    self.isChangeEmoji = false
    if modelSpine == nil or emojiId == nil then
        return
    end
    local emoji = modelSpine:GetChild("emoji");
    local showHelloController = modelSpine:GetController("ifGetHello");
    showHelloController.selectedIndex = 1;
    emoji.url = "ui://Emoji/e"..emojiId;
    self.emojiTimerId = utimer.timeCall(function ()
        showHelloController.selectedIndex = 0;
    end , HelperFunc.GetGlobalNumVlue(188) * 1000, 1);
end


function CityPlayer:OnTouchBegin()
    if CityPlayerMgr.HasPickUpPlayer() then
        return
    end
    self.isPlayDrag = false
    CityPlayerMgr.StartPickUp(self)
end
function CityPlayer:OnTouchMove()
    if self.isPlayDrag then
        return
    end
    self.isPlayDrag = true
    --主城拎起小人
    local _index = Mathf.Random(26,27)
    AudioManager.PlayInteractionVoice(G.dataTable["t_hero"][tostring(self.info.head)].f_HeroID,0,
            AudioManager.InteractionTagTable[_index].Tag)
end

function CityPlayer:OnTouchEnd()
    CityPlayerMgr.EndPickUp()
end

function CityPlayer:ClickOtherPlayer()
    --主城点击小人
    local _index = Mathf.Random(22,23)
    AudioManager.PlayInteractionVoice(G.dataTable["t_hero"][tostring(self.info.head)].f_HeroID,0,AudioManager.InteractionTagTable[_index].Tag)
    roleInfoHandler.sendreqOtherRoleInfo(self.info.roleId, true);
end
